`default_nettype none
`timescale 1 ns / 1 ns

module tb_cyclic_code();
    localparam MESSAGE_VECTOR = 12'b1111_1100_0100;
    localparam ERROR_VECTOR = 23'b010_0000_1000_0001_0000_0000; // 错误必须<=3才能纠错成功
    reg clk  ;
    reg rst_n;

    reg         encode_start   ;
    wire        encode_busy    ;
    wire        encode_done    ;
    wire [22:0] encode_data_out;

    reg         decode_start   ;
    wire [22:0] decode_data_in ;
    wire        decode_busy    ;
    wire        decode_done    ;
    wire [11:0] decode_data_out;
    wire        error_trapped  ;

    assign decode_data_in = encode_data_out ^ ERROR_VECTOR;

    initial begin
        $dumpfile("tb_cyclic_code.vcd");
        $dumpvars(0, tb_cyclic_code);
        wait(decode_done);
        if (decode_data_out == MESSAGE_VECTOR) begin
            $display("Success");
        end else begin
            if (error_trapped) begin
                $display("Failed and output other codewords");
            end else begin
                $display("Error corrected but detected");
            end
        end
        repeat(5) @(posedge clk);
        $finish;
    end

    initial begin
        #2000;
        $finish;
    end
    
    initial begin
        clk = 0;
        forever begin
            #1 clk = ~clk;
        end
    end

    initial begin
        rst_n = 0; #5
        rst_n = 1;
    end

    initial begin
        encode_start <= 0;
        wait(rst_n);
        @(posedge clk) begin
            encode_start <= 1;
        end
        @ (posedge clk) begin
            encode_start <= 0;
        end
    end

    initial begin
        decode_start <= 0;
        wait(encode_done);
        @(posedge clk) begin
            decode_start <= 1;
        end
        @(posedge clk) begin
            decode_start <= 0;
        end
    end

    cyclic_code_encode u_cyclic_code_encode(
        .clk      (clk            ),
        .rst_n    (rst_n          ),
        .start    (encode_start   ),
        .data_in  (MESSAGE_VECTOR ),
        .busy     (encode_busy    ),
        .done     (encode_done    ),
        .data_out (encode_data_out)
    );

    cyclic_code_decode u_cyclic_code_decode(
        .clk           (clk             ),
        .rst_n         (rst_n           ),
        .start         (decode_start   ),
        .data_in       (decode_data_in ),
        .busy          (decode_busy    ),
        .done          (decode_done    ),
        .data_out      (decode_data_out),
        .error_trapped (error_trapped   )
    );
endmodule